#include "my_popen.h"

static pid_t *pids = NULL;
static const int max_size = 1024;

FILE *my_popen(const char *command, const char *type){
    if((type[0] != 'r' && type[0] != 'w') || type[1] != '\0'){
        errno = EINVAL;
        return NULL;
    }
    int fd[2];
    FILE* fp;
    pid_t pid;
    
    if(pids == NULL){
        pids = (pid_t*)calloc(max_size, sizeof(pid_t));
        if(pids == NULL){
            errno = ENOMEM;
            return NULL;
        }
    }

    if(pipe(fd) < 0){
        return NULL;
    } 
    
    if((pid = fork()) == -1){
        return NULL;
    }
  
    if(pid == 0){
        if(type[0] == 'r'){
            close(fd[0]);
            if(fd[1] != STDOUT_FILENO){
                dup2(fd[1], STDOUT_FILENO);
                close(fd[1]);
            }
        }else{
            close(fd[1]);
            if(fd[0] != STDIN_FILENO){
                dup2(fd[0], STDIN_FILENO);
                close(fd[0]);
            }
        }
        execl("/bin/sh", "sh", "-c", command, NULL);
        exit(1);
    }
    
    if(type[0] == 'r'){
        close(fd[1]);
        fp = fdopen(fd[0], type);
    }else{
        close(fd[0]);
        fp = fdopen(fd[1], type);
    }
    if(fp == NULL){
        return NULL;
    }
    pids[fileno(fp)] = pid;
    return fp;
}


int my_pclose(FILE *stream){
    int status;
    pid_t pid;
    if(pids == NULL){
        errno = EINVAL;
        return -1;
    }
    int fd = fileno(stream);
    if(fd == -1){
        return -1;
    }
    pid = pids[fd];
    fclose(stream);
    waitpid(pid, &status, 0);
    return status;
}